package utils

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"sync"
	"time"
	"net/http"
	"bytes"
	"io" // 新增导入

	"github.com/beego/beego/v2/server/web"
)

// 全局 SPDK 客户端实例及锁
var spdkClientOnce sync.Once
var spdkClient *SPDKClient

// 新增：SPDKResponse 与 SPDKError 类型定义
type SPDKResponse struct {
	JsonRPC string      `json:"jsonrpc"`
	ID      int         `json:"id"`
	Result  interface{} `json:"result,omitempty"`
	Error   *SPDKError  `json:"error,omitempty"`
}

type SPDKError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// SPDKClient 封装了 GenericRPCClient，使调用统一走 JSON-RPC 层
type SPDKClient struct {
	// 注意：此处只保留 BaseURL 调用逻辑，其他细节略
	BaseURL   string
	rpcClient *GenericRPCClient
	URL      string
	Username string
	Password string
}

// GetSPDKClient 返回全局 SPDKClient 实例
func GetSPDKClient() *SPDKClient {
	spdkClientOnce.Do(func() {
		var err error
		spdkClient, err = NewSPDKClient()
		if (err != nil) {
			LogError(fmt.Sprintf("Failed to create SPDK client: %v", err))
		}
	})
	return spdkClient
}

// NewSPDKClient 从配置中构造 SPDKClient（无参版本）
func NewSPDKClient() (*SPDKClient, error) {
	spdkURL, err := web.AppConfig.String("spdk::url")
	if err != nil || spdkURL == "" {
		return nil, errors.New("spdk url not configured")
	}
	parsed, err := url.Parse(spdkURL)
	if err != nil || parsed.Host == "" {
		return nil, errors.New("invalid spdk url")
	}
	if (!strings.HasPrefix(spdkURL, "http://") && !strings.HasPrefix(spdkURL, "https://")) {
		return nil, errors.New("spdk url must start with http:// or https://")
	}

	spdkUser, _ := web.AppConfig.String("spdk::username")
	spdkPass, _ := web.AppConfig.String("spdk::password")

	client := &GenericRPCClient{
		URL:      spdkURL,
		Timeout:  time.Duration(web.AppConfig.DefaultInt("spdk::timeout", 30)) * time.Second,
		Username: spdkUser,
		Password: spdkPass,
	}
	return &SPDKClient{
		BaseURL:   spdkURL,
		rpcClient: client,
		URL:      spdkURL,
		Username: spdkUser,
		Password: spdkPass,
	}, nil
}

// Call 将方法和参数封装后委托给 GenericRPCClient，并增加 debug log
func (c *SPDKClient) Call(method string, params interface{}) (*SPDKResponse, error) {
	respMap, err := c.rpcClient.Call(method, params)
	if err != nil {
		return nil, fmt.Errorf("rpc call error: %v", err)
	}

	// Debug 输出响应信息
	fmt.Printf("DEBUG: JSON-RPC Raw response: %v\n", respMap)

	// 将 map 转换为 SPDKResponse 结构
	data, err := json.Marshal(respMap)
	if err != nil {
		return nil, fmt.Errorf("marshal rpc response error: %v", err)
	}

	var spdkResp SPDKResponse
	if err := json.Unmarshal(data, &spdkResp); err != nil {
		return nil, fmt.Errorf("parse rpc response error: %v", err)
	}

	return &spdkResp, nil
}

// CallWithRetry 增加重试机制，实现远程RPC调用优化
func (c *SPDKClient) CallWithRetry(method string, params interface{}, retries int, delay time.Duration) (*SPDKResponse, error) {
	var spdkResp *SPDKResponse
	var err error
	for i := 0; i < retries; i++ {
		spdkResp, err = c.Call(method, params)
		if err == nil {
			return spdkResp, nil
		}
		time.Sleep(delay)
	}

	return nil, fmt.Errorf("remote rpc call %s failed after %d retries: %v", method, retries, err)
}

// CreateMallocBdev 调用 SPDK bdev_malloc_create 接口
func (c *SPDKClient) CreateMallocBdev(name string, sizeMB int) error {
	// 构造请求参数
	params := map[string]interface{}{
		"name":       name,
		"num_blocks": sizeMB * 1024 * 1024 / 512, // 假设每块512字节
		"block_size": 512,
	}
	reqBody, err := json.Marshal(map[string]interface{}{
		"id":      1,
		"jsonrpc": "2.0",
		"method":  "bdev_malloc_create",
		"params":  params,
	})
	if err != nil {
		return err
	}

	// 使用自定义请求构造，并设置 Basic Auth
	req, err := http.NewRequest("POST", c.URL, bytes.NewReader(reqBody))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.SetBasicAuth(c.Username, c.Password) // 设置用户名和密码

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	if len(body) == 0 {
		return nil // 空响应视为成功
	}

	var rpcResp SPDKResponse
	if err := json.Unmarshal(body, &rpcResp); err != nil {
		return err
	}

	if rpcResp.Error != nil {
		return fmt.Errorf("SPDK error: %s", rpcResp.Error.Message)
	}
	return nil
}

// CreateAioBdev 创建AIO后端设备
func (c *SPDKClient) CreateAioBdev(name string, filename string) error {
	params := map[string]interface{}{
		"name":     name,
		"filename": filename,
	}
	_, err := c.Call("bdev_aio_create", params)
	return err
}

// CreateNVMeBdev 创建NVMe后端设备
func (c *SPDKClient) CreateNVMeBdev(name string, traddr string, transport string) error {
	params := map[string]interface{}{
		"name":   name,
		"trtype": transport,
		"traddr": traddr,
	}
	_, err := c.Call("bdev_nvme_attach_controller", params)
	return err
}

// DeleteBdev 删除后端设备（修改方法名称为 bdev_malloc_delete）
func (c *SPDKClient) DeleteBdev(name string) error {
	params := map[string]string{
		"name": name,
	}
	_, err := c.Call("bdev_malloc_delete", params)
	return err
}

// GetBdevs 获取所有后端设备信息
func (c *SPDKClient) GetBdevs() ([]map[string]interface{}, error) {
	resp, err := c.Call("bdev_get_bdevs", nil)
	if err != nil {
		return nil, err
	}
	// 确保返回值是一个切片
	bdevs, ok := resp.Result.([]interface{})
	if !ok {
		return nil, fmt.Errorf("invalid bdevs response format")
	}

	// 将切片中的每个元素转换为 map[string]interface{}
	var bdevList []map[string]interface{}
	for _, bdev := range bdevs {
		bdevMap, ok := bdev.(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("invalid bdev element format")
		}
		bdevList = append(bdevList, bdevMap)
	}
	return bdevList, nil
}

// CreateNVMFSubsystem 创建NVMe-oF子系统
func (c *SPDKClient) CreateNVMFSubsystem(nqn string, serial string, allowAnyHost bool, hosts []string) error {
	_, err := c.Call("nvmf_create_subsystem", map[string]interface{}{
		"nqn":            nqn,
		"serial_number":  serial,
		"allow_any_host": allowAnyHost,
		"hosts":          hosts,
	})
	return err
}

// AddNVMFNamespace 添加命名空间到子系统
func (c *SPDKClient) AddNVMFNamespace(nqn string, bdevName string, nsid uint32) error {
	_, err := c.Call("nvmf_subsystem_add_ns", map[string]interface{}{
		"nqn": nqn,
		"namespace": map[string]interface{}{
			"nsid":      nsid,
			"bdev_name": bdevName,
		},
	})
	return err
}

// AddNVMFListener 添加监听器到子系统
func (c *SPDKClient) AddNVMFListener(nqn string, transport string, address string, port uint16) error {
	_, err := c.Call("nvmf_subsystem_add_listener", map[string]interface{}{
		"nqn": nqn,
		"listen_address": map[string]interface{}{
			"trtype":  transport,
			"adrfam":  "ipv4",
			"traddr":  address,
			"trsvcid": fmt.Sprintf("%d", port),
		},
	})
	return err
}

// Bdev相关方法
func (c *SPDKClient) GetBdevStats() (interface{}, error) {
	resp, err := c.Call("bdev_get_iostat", nil)
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}

// Subsystem相关方法
func (c *SPDKClient) GetSubsystems() (interface{}, error) {
	resp, err := c.Call("nvmf_get_subsystems", nil)
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}

func (c *SPDKClient) DeleteSubsystem(nqn string) error {
	_, err := c.Call("nvmf_delete_subsystem", map[string]interface{}{
		"nqn": nqn,
	})
	return err
}

func (c *SPDKClient) GetListeners(nqn string) (interface{}, error) {
	resp, err := c.Call("nvmf_get_listeners", map[string]interface{}{
		"nqn": nqn,
	})
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}

// Transport相关方法
func (c *SPDKClient) GetTransports() (interface{}, error) {
	resp, err := c.Call("nvmf_get_transports", nil)
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}

// AddNamespaceToSubsystem 添加命名空间到子系统
func (c *SPDKClient) AddNamespaceToSubsystem(nqn string, bdevName string, nsid uint32, nguid string, eui64 string) error {
	params := map[string]interface{}{
		"nqn": nqn,
		"namespace": map[string]interface{}{
			"bdev_name": bdevName,
			"nsid":      nsid,
		},
	}

	if nguid != "" {
		params["namespace"].(map[string]interface{})["nguid"] = nguid
	}
	if eui64 != "" {
		params["namespace"].(map[string]interface{})["eui64"] = eui64
	}

	_, err := c.Call("nvmf_subsystem_add_ns", params)
	return err
}

// RemoveNamespaceFromSubsystem 从子系统移除命名空间
func (c *SPDKClient) RemoveNamespaceFromSubsystem(nqn string, nsid uint32) error {
	_, err := c.Call("nvmf_subsystem_remove_ns", map[string]interface{}{
		"nqn":  nqn,
		"nsid": nsid,
	})
	return err
}

// 新增子系统管理方法
func (c *SPDKClient) GetSubsystemStats() (interface{}, error) {
	resp, err := c.Call("nvmf_get_stats", nil)
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}

func (c *SPDKClient) SetSubsystemOptions(nqn string, allowAnyHost bool, maxNamespaces uint32) error {
	_, err := c.Call("nvmf_subsystem_set_options", map[string]interface{}{
		"nqn":             nqn,
		"allow_any_host":  allowAnyHost,
		"max_namespaces":  maxNamespaces,
	})
	return err
}

// 新增主机管理方法
func (c *SPDKClient) AddHostToSubsystem(nqn string, hostNQN string) error {
	_, err := c.Call("nvmf_subsystem_add_host", map[string]interface{}{
		"nqn":  nqn,
		"host": hostNQN,
	})
	return err
}

func (c *SPDKClient) RemoveHostFromSubsystem(nqn string, hostNQN string) error {
	_, err := c.Call("nvmf_subsystem_remove_host", map[string]interface{}{
		"nqn":  nqn,
		"host": hostNQN,
	})
	return err
}

// 新增监听器管理方法
func (c *SPDKClient) RemoveListener(nqn string, trtype string, adrfam string, traddr string, trsvcid string) error {
	_, err := c.Call("nvmf_subsystem_remove_listener", map[string]interface{}{
		"nqn": nqn,
		"listen_address": map[string]interface{}{
			"trtype":  trtype,
			"adrfam":  adrfam,
			"traddr":  traddr,
			"trsvcid": trsvcid,
		},
	})
	return err
}

// 新增传输层管理方法
func (c *SPDKClient) CreateTransport(trtype string, maxQueueDepth uint32, maxIOQpairs uint32) error {
	config := map[string]interface{}{
		"trtype":          trtype,
		"max_queue_depth": maxQueueDepth,
		"max_io_qpairs":   maxIOQpairs,
	}
	_, err := c.CallWithRetry("nvmf_create_transport", config, 3, 500*time.Millisecond)
	return err
}

// 新增全局配置方法
func (c *SPDKClient) SetGlobalNVMFConfig(maxSubsystems uint32, maxNamespaces uint32) error {
	_, err := c.Call("nvmf_set_config", map[string]interface{}{
		"max_subsystems":               maxSubsystems,
		"max_namespaces_per_subsystem": maxNamespaces,
	})
	return err
}

// SetSubsystemQoS 设置子系统QoS参数
func (c *SPDKClient) SetSubsystemQoS(nqn string, qosParams map[string]interface{}) error {
	params := map[string]interface{}{
		"nqn": nqn,
		"qos": qosParams,
	}

	_, err := c.Call("nvmf_subsystem_set_qos", params)
	return err
}

// GetNamespaceStats 获取命名空间性能统计
func (c *SPDKClient) GetNamespaceStats(nqn string, nsid uint32) (interface{}, error) {
	params := map[string]interface{}{
		"nqn":  nqn,
		"nsid": nsid,
	}

	resp, err := c.Call("nvmf_get_ns_stats", params)
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}

// SetNamespaceOptions 设置命名空间选项
func (c *SPDKClient) SetNamespaceOptions(nqn string, nsid uint32, options map[string]interface{}) error {
	params := map[string]interface{}{
		"nqn":     nqn,
		"nsid":    nsid,
		"options": options,
	}

	_, err := c.Call("nvmf_subsystem_set_ns_options", params)
	return err
}

// GetVersion 获取SPDK版本信息
func (c *SPDKClient) GetVersion() (string, error) {
	// 调用时不传递任何参数
	resp, err := c.CallWithRetry("spdk_get_version", nil, 3, 500*time.Millisecond)
	if err != nil {
		return "", err
	}
	
	// 解析版本信息
	versionInfo, ok := resp.Result.(map[string]interface{})
	if (!ok) {
		return "", fmt.Errorf("invalid version response format")
	}
	version, ok := versionInfo["version"].(string)
	if (!ok) {
		return "", fmt.Errorf("version field not found in response")
	}
	return version, nil
}

// GetSystemStats 获取SPDK系统统计信息
func (c *SPDKClient) GetSystemStats() (interface{}, error) {
	resp, err := c.Call("framework_get_subsystems", nil) // 修正方法名
	if err != nil {
		return nil, err
	}
	return resp.Result, nil
}